import z from 'zod'
import env from '../../utils/env'
import fs from 'fs'
import { infoLog, traceLog } from '../../utils/log'
import { generateResources } from '../../models'

export type RpcMethod = <T, U>(param: T) => Promise<U>

export type RpcMethodConfig<T, U> = {
    handler: RpcMethod
    auth: boolean
    validator: z.ZodSchema
    paramType: string
    returnType: string
}

const rpcs = new Map<string, RpcMethodConfig<unknown, unknown>>()

/**
 * ### 注册rpc方法
 * @param name 
 * @param rpc 
 */
export const registerRpcMethod = (rpc: RpcMethodConfig<unknown, unknown>[]) => {
    for (const item of rpc) {
        rpcs.set(item.handler.name, item)
    }
}

/**
 * ### 获取rpc方法
 * @param name 
 * @returns 
 */
export const getRpcMethod = (name: string) => {
    return rpcs.get(name)
}

/** 生成前端rpc调用方法文件 */
export const generateRpcClient = () => {

    // 仅开发环境生成
    if (env.NODE_ENV !== 'development') return

    [...rpcs.keys()].forEach(item => infoLog(`注册rpc方法:${item}`))

    const rpcString = `
import type { ${[...rpcs.values()].map(item => item.paramType).join(',')}, IRspApi } from "@packages/shared"

/** 可访问的资源名称 */
export const CONST_Resource = {
${generateResources().map(item => `    ${item}: '${item}',`).join('\n')}
} as const

export type OnSuccess = (<T>(data: T) => void) | undefined
export type OnBusinessError = ((msg: string) => void) | undefined
export type OnError = (<T>(data: T) => void) | undefined

export type HttpConfig<T> = {
    param: T
    onSuccess?: OnSuccess
    onBusinessError?: OnBusinessError
    onError?: OnError
}

/** 
 * ### 请求适配器 
 * 
 * 可根据需要自定义适配器，如：axios、fetch、uni.request等
 * 
 * 默认提供了简易的 fetch 适配器，也可以实现自己的请求适配器
 * 
 */
export type RequestAdapter = <T>(url: string, options: RequestInit) => Promise<{ json(): Promise<T> }>;


export const http = async <T>(
  baseUrl: string,
  method: string,
  config: HttpConfig<T>,
  adapter: RequestAdapter = fetch  // 默认使用 fetch
) => {
  try {
    const result = await adapter(baseUrl + '/' + method, {
      method: 'POST',
      body: JSON.stringify(config.param),
      headers: {
        'Content-Type': 'application/json'
      }
    });

    const res = (await result.json()) as IRspApi;
    if (res.code === 200)
      config.onSuccess && config.onSuccess(res.data);
    else
      config.onBusinessError && config.onBusinessError(res.msg);
  } catch (error) {
    config.onError && config.onError(error);
  }
};

export const baseUrl = 'http://localhost:${env.PORT}/api/rpc/v1'

export const const_API = {
${[...rpcs.values()].map(item => {
        return '    ' + item.handler.name + `: (config: HttpConfig<${item.paramType}>, adapter?: RequestAdapter) => http(baseUrl, '${item.handler.name}', config, adapter),`
    }).join('\n')
        // registerNewUser: (param: IReqCreateUser, doSuccess: DoSuccess, doBusinessError: DoBusinessError, doError: DoError) => http<IReqCreateUser>(baseUrl, param, doSuccess, doBusinessError, doError)
        }
} as const

    `

    // console.log(rpcString)
    fs.writeFileSync(env.API_TS_URL, rpcString)

    traceLog(`生成rpc方法文件成功:${env.API_TS_URL}`)

}